#include "inc/fmod.hpp"
#include <stdlib.h>
#include <unistd.h>
#include  "com_handsome_ndkvoice_Utils.h"

#include <jni.h>

#include <android/log.h>
#define LOGI(FORMAT,...) __android_log_print(ANDROID_LOG_INFO,"cwp",FORMAT,##__VA_ARGS__);
#define LOGE(FORMAT,...) __android_log_print(ANDROID_LOG_ERROR,"cwp",FORMAT,##__VA_ARGS__);

#define MODE_NORMAL 0
#define MODE_LUOLI 1
#define MODE_DASHU 2
#define MODE_JINGSONG 3
#define MODE_GAOGUAI 4
#define MODE_KONGLING 5


int playState = 0;
int playBgmState = 0;
//混响模式
int iReverationType = 0;
//变音模式
int iInflectionSound = 0;
int channel_index = 0;
int channel_vol[2] = {0};
int frq_gain[10] = {0};
int bSetEQ = 0;

using namespace FMOD;

JNIEXPORT void JNICALL Java_com_handsome_ndkvoice_Utils_main(JNIEnv *env,
		jclass jcls, jstring path_jstr, jstring bgmpath_jstr, jint type) {
    //声音引擎
	System *system;
    //声音
	Sound *sound, *bgm_sound;
    FMOD_RESULT ret;
	//数字处理（音效）
    DSP *dsp = nullptr;
    DSP *hdsp = nullptr;
    //正在播放
	bool playing = false;
	bool bgmplaying = false;
	//音乐轨道

    int channelsplaying = 0;
    Channel *channel;
    Channel *bgmchannel;
    ChannelGroup *soundGroup;
    ChannelGroup *bgmGroup;
    ChannelGroup *masterGroup;
	//播放速度
    float frequency = 0;
    static int curtype = -1;
    static int CurChannelVol[2] = {0};
    //音频地址
    const char* path_cstr = env->GetStringUTFChars(path_jstr, NULL);
    const char* bgm_path_cstr = env->GetStringUTFChars(bgmpath_jstr, NULL);

    System_Create(&system);

//    if(type == 1)   //创建音轨
    {

        system->init(32, FMOD_INIT_NORMAL, NULL);

        //创建声音
        system->createSound(path_cstr, FMOD_LOOP_NORMAL, 0, &sound);

        system->createSound(bgm_path_cstr, FMOD_DEFAULT, 0, &bgm_sound);

        system->createChannelGroup("sound", &soundGroup);
        system->createChannelGroup("bgmSound", &bgmGroup);
        system->getMasterChannelGroup(&masterGroup);

        masterGroup->addGroup(soundGroup);
        masterGroup->addGroup(bgmGroup);
    }


    do{

        if(playState == 1)
        {
            //播放音频
            channel->isPlaying(&playing);

            if(!playing)
            {
                bSetEQ = 1;
                system->playSound(sound, 0, true, &channel);
//                channel->setChannelGroup(soundGroup);
                channel->setChannelGroup(soundGroup);
                channel->setPaused(false);
                soundGroup->setMute(false);
                soundGroup->setVolume(0.5);
            }

            if(CurChannelVol[0] != channel_vol[0]) {
                CurChannelVol[0] = channel_vol[0];
                LOGI("sound vol%d ", channel_vol[0]);
                if (CurChannelVol[0] <= 100 && CurChannelVol[0] > 0) {
                    soundGroup->setMute(false);
                    soundGroup->setVolume((float) (CurChannelVol[0] / 100.0));
                }
                else if(CurChannelVol[0] == 0)
                {
                    soundGroup->setMute(true);
                }

            }

            if(curtype != iReverationType) {
                curtype = iReverationType;

                try {
                    LOGI("iReverationtype:%d\r\n", iReverationType);
                    switch (iReverationType) {
                        case MODE_NORMAL:
                            if (dsp)
                                channel->removeDSP(dsp);
                            break;
                        case MODE_LUOLI:
                            //提升或者降低音调的一种音效
                            system->createDSPByType(FMOD_DSP_TYPE_PITCHSHIFT, &dsp);
                            //设置音调的参数
                            dsp->setParameterFloat(FMOD_DSP_PITCHSHIFT_PITCH, 1.8);
                            //添加进到channel，添加进轨道
                            channel->addDSP(0, dsp);
                            break;
                        case MODE_DASHU:
                            system->createDSPByType(FMOD_DSP_TYPE_PITCHSHIFT, &dsp);
                            dsp->setParameterFloat(FMOD_DSP_PITCHSHIFT_PITCH, 0.8);
                            channel->addDSP(0, dsp);
                            break;
                        case MODE_JINGSONG:
                            system->createDSPByType(FMOD_DSP_TYPE_TREMOLO, &dsp);
                            dsp->setParameterFloat(FMOD_DSP_TREMOLO_SKEW, 0.8);
                            channel->addDSP(0, dsp);
                            break;
                        case MODE_GAOGUAI:
                            //提高说话的速度
                            system->playSound(sound, 0, false, &channel);
                            channel->getFrequency(&frequency);
                            frequency = frequency * 2;
                            channel->setFrequency(frequency);
                            break;
                        case MODE_KONGLING:
                            system->createDSPByType(FMOD_DSP_TYPE_ECHO, &dsp);
                            dsp->setParameterFloat(FMOD_DSP_ECHO_DELAY, 300);
                            dsp->setParameterFloat(FMOD_DSP_ECHO_FEEDBACK, 20);
                            channel->addDSP(0, dsp);
                            break;
                    }
                } catch (...) {
                    LOGE("%s", "发生异常");
                    goto end;
                }
                system->update();
            }
        }
        if(playBgmState)
        {
            //播放音频
            bgmchannel->isPlaying(&bgmplaying);

            if(!bgmplaying)
            {
                ret = system->playSound(bgm_sound, 0, true, &bgmchannel);
                LOGI("bgm play state%d  ret:%d", playBgmState, ret);
                bgmchannel->setChannelGroup(bgmGroup);
                bgmchannel->setPaused(false);
                bgmGroup->setMute(false);
                bgmGroup->setVolume(0.5);
            }
            if(CurChannelVol[1] != channel_vol[1]) {
                CurChannelVol[1] = channel_vol[1];

                LOGI("bgm vol%d ", channel_vol[1]);
                if (CurChannelVol[1] <= 100 && CurChannelVol[1] > 0) {
                    bgmGroup->setMute(false);
                    bgmGroup->setVolume((float) (CurChannelVol[1] / 100.0));
                }
                else if(CurChannelVol[1] == 0)
                {
                    bgmGroup->setMute(true);
                }

            }
            system->update();

        }

        if(bSetEQ)
        {
            bSetEQ = 0;
            if(dsp)
                channel->removeDSP(dsp);
            system->createDSPByType(FMOD_DSP_TYPE_MULTIBAND_EQ, &dsp);
            dsp->setParameterInt(FMOD_DSP_MULTIBAND_EQ_A_FILTER, FMOD_DSP_MULTIBAND_EQ_FILTER_PEAKING);
            dsp->setParameterFloat(FMOD_DSP_MULTIBAND_EQ_A_FREQUENCY, 32);
//            dsp->setParameterFloat(FMOD_DSP_MULTIBAND_EQ_A_Q, 0.707);
            dsp->setParameterFloat(FMOD_DSP_MULTIBAND_EQ_A_GAIN, frq_gain[0]);
            dsp->setParameterInt(FMOD_DSP_MULTIBAND_EQ_B_FILTER, FMOD_DSP_MULTIBAND_EQ_FILTER_PEAKING);
            dsp->setParameterFloat(FMOD_DSP_MULTIBAND_EQ_B_FREQUENCY, 65);
//            dsp->setParameterFloat(FMOD_DSP_MULTIBAND_EQ_B_Q, 0.707);
            dsp->setParameterFloat(FMOD_DSP_MULTIBAND_EQ_B_GAIN, frq_gain[1]);
            dsp->setParameterInt(FMOD_DSP_MULTIBAND_EQ_C_FILTER, FMOD_DSP_MULTIBAND_EQ_FILTER_PEAKING);
            dsp->setParameterFloat(FMOD_DSP_MULTIBAND_EQ_C_FREQUENCY, 125);
//            dsp->setParameterFloat(FMOD_DSP_MULTIBAND_EQ_C_Q, 0.707);
            dsp->setParameterFloat(FMOD_DSP_MULTIBAND_EQ_C_GAIN, frq_gain[2]);
            dsp->setParameterInt(FMOD_DSP_MULTIBAND_EQ_D_FILTER, FMOD_DSP_MULTIBAND_EQ_FILTER_PEAKING);
            dsp->setParameterFloat(FMOD_DSP_MULTIBAND_EQ_D_FREQUENCY, 250);
//            dsp->setParameterFloat(FMOD_DSP_MULTIBAND_EQ_D_Q, 0.707);
            dsp->setParameterFloat(FMOD_DSP_MULTIBAND_EQ_D_GAIN, frq_gain[3]);
            dsp->setParameterInt(FMOD_DSP_MULTIBAND_EQ_E_FILTER, FMOD_DSP_MULTIBAND_EQ_FILTER_PEAKING);
            dsp->setParameterFloat(FMOD_DSP_MULTIBAND_EQ_E_FREQUENCY, 500);
//            dsp->setParameterFloat(FMOD_DSP_MULTIBAND_EQ_E_Q, 0.707);
            dsp->setParameterFloat(FMOD_DSP_MULTIBAND_EQ_E_GAIN, frq_gain[4]);
            channel->addDSP(0, dsp);


            if(hdsp)
                channel->removeDSP(hdsp);
            system->createDSPByType(FMOD_DSP_TYPE_MULTIBAND_EQ, &hdsp);
            hdsp->setParameterInt(FMOD_DSP_MULTIBAND_EQ_A_FILTER, FMOD_DSP_MULTIBAND_EQ_FILTER_PEAKING);
            hdsp->setParameterFloat(FMOD_DSP_MULTIBAND_EQ_A_FREQUENCY, 1000);
//            hdsp->setParameterFloat(FMOD_DSP_MULTIBAND_EQ_A_Q, 0.707);
            hdsp->setParameterFloat(FMOD_DSP_MULTIBAND_EQ_A_GAIN, frq_gain[5]);
            hdsp->setParameterInt(FMOD_DSP_MULTIBAND_EQ_B_FILTER, FMOD_DSP_MULTIBAND_EQ_FILTER_PEAKING);
            hdsp->setParameterFloat(FMOD_DSP_MULTIBAND_EQ_B_FREQUENCY, 2000);
//            hdsp->setParameterFloat(FMOD_DSP_MULTIBAND_EQ_B_Q, 0.707);
            hdsp->setParameterFloat(FMOD_DSP_MULTIBAND_EQ_B_GAIN, frq_gain[6]);
            hdsp->setParameterInt(FMOD_DSP_MULTIBAND_EQ_C_FILTER, FMOD_DSP_MULTIBAND_EQ_FILTER_PEAKING);
            hdsp->setParameterFloat(FMOD_DSP_MULTIBAND_EQ_C_FREQUENCY, 4000);
//            hdsp->setParameterFloat(FMOD_DSP_MULTIBAND_EQ_C_Q, 0.707);
            hdsp->setParameterFloat(FMOD_DSP_MULTIBAND_EQ_C_GAIN, frq_gain[7]);
            hdsp->setParameterInt(FMOD_DSP_MULTIBAND_EQ_D_FILTER, FMOD_DSP_MULTIBAND_EQ_FILTER_PEAKING);
            hdsp->setParameterFloat(FMOD_DSP_MULTIBAND_EQ_D_FREQUENCY, 8000);
//            hdsp->setParameterFloat(FMOD_DSP_MULTIBAND_EQ_D_Q, 0.707);
            hdsp->setParameterFloat(FMOD_DSP_MULTIBAND_EQ_D_GAIN, frq_gain[8]);
            hdsp->setParameterInt(FMOD_DSP_MULTIBAND_EQ_E_FILTER, FMOD_DSP_MULTIBAND_EQ_FILTER_PEAKING);
            hdsp->setParameterFloat(FMOD_DSP_MULTIBAND_EQ_E_FREQUENCY, 16000);
//            hdsp->setParameterFloat(FMOD_DSP_MULTIBAND_EQ_E_Q, 0.707);
            hdsp->setParameterFloat(FMOD_DSP_MULTIBAND_EQ_E_GAIN, frq_gain[9]);

            channel->addDSP(0, hdsp);
            LOGI("FMOD_DSP_TYPE_MULTIBAND_EQ set frq: gain%d", frq_gain[0]);

            system->update();
        }

//        if(!playing)
//            playState = 0;
//        if(!bgmplaying)
//            playBgmState = 0;
//        bgmchannel->isPlaying(&bgmplaying);
//        channel->isPlaying(&playing);
        system->getChannelsPlaying(&channelsplaying, NULL);

    }while(channelsplaying);

    //释放资源
    end: env->ReleaseStringUTFChars(path_jstr, path_cstr);
	sound->release();
	system->close();
	system->release();
}


JNIEXPORT void JNICALL Java_com_handsome_ndkvoice_Utils_SetChannelVolume(JNIEnv *env, jclass jcls, jint channel, jint vol)
{
    channel_index = channel;
    if(channel_index < 2)
    {
        channel_vol[channel_index] = vol;
    }
    LOGI("set vol[%d]:%d ", channel_index, channel_vol[channel_index]);

}

JNIEXPORT void JNICALL Java_com_handsome_ndkvoice_Utils_SetEQ(JNIEnv *env, jclass jcls, jint frq, jint gain, jint qvalue) {
    if (frq < 10)
    {
        frq_gain[frq] = gain - 11;
        bSetEQ = 1;
    }

    LOGI("EQ set frq:%d  gain%d", frq, frq_gain[frq]);

}


JNIEXPORT void JNICALL Java_com_handsome_ndkvoice_Utils_PlayState(JNIEnv *env,
                                                                      jclass jcls, jint play)
{
    if(play &0x10)
    {
        playBgmState = 1;
    }
    else
        playState = play;
}

JNIEXPORT void JNICALL Java_com_handsome_ndkvoice_Utils_SetReveration(JNIEnv *env,
                                                                         jclass jcls, jint type)
{
    iReverationType = type;
}

JNIEXPORT void JNICALL Java_com_handsome_ndkvoice_Utils_SetInflectionSound(JNIEnv *env,
                                                                      jclass jcls, jint type)
{
    iInflectionSound = type;
}
